package cshi.common;


import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

interface Generator<T> {
	T next();
}

//基本类型不能作为类型参数
class Fibonacci implements Generator<Integer>{
	private int fib(int n) {
		return (n < 2) ? 1: fib(n-1) + fib(n-2);
	}
	@Override
	public Integer next() {
		return fib(cnt++);
	}
	
	private int cnt;
}

//更进一步，编写一个实现了Iterable的Fibonacci生成器
class InterableFibonacci extends Fibonacci implements Iterable<Integer>{

	public Iterator<Integer> iterator() {
		return new Iterator<Integer>() {

			@Override
			public boolean hasNext() {
				return n > 0;
			}

			@Override
			public Integer next() {
				n--;
				return InterableFibonacci.this.next();
			}

			@Override
			public void remove() {
				throw new UnsupportedOperationException();
				
			}
		};
	}
	public InterableFibonacci(int count) {
		n = count;
	}
	private int n;
}

//as long as you can, try to use generic method as more as possible
class GenericMethod {
	public <T> void f(T x) {
		System.out.println(x.getClass().getName());
	}
	
	//variable args and generic method
	public <T> List<T> makeList(T... args) {
		List<T> result = new ArrayList<T>();
		for (T item: args)
			result.add(item);
		return result;
	}
}

//construct a generator for any class
class BasicGenerator<T> implements Generator<T>{
	private Class<T> type;
	public BasicGenerator(Class<T> type){
		this.type = type;
	}
	@Override
	public T next() {
		try {
			return type.newInstance();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public static <T> Generator<T> create(Class<T> type) {
		return new BasicGenerator<T>(type);
	}
}
public class GenericTest {

	public static void testFibonacci() {
		Fibonacci gen = new Fibonacci();
		for (int i=0; i<10; i++)
			System.out.print(gen.next() + " ");
	}
	public static void testInterableFibonacci() {
		for (int i:new InterableFibonacci(10))
			System.out.print(i + " ");
	}
	public static void testGenericMethod() {
		GenericMethod gm = new GenericMethod();
		gm.f("");
		gm.f(1);
		gm.f(1.0f);
		gm.f(gm);
		
		System.out.println(gm.makeList("a","b"));
	}
	public static void main(String[] args) {
		testGenericMethod();
		//testFibonacci();
		//testInterableFibonacci();
	}

}
